package ru.usu.gv.utils.generators;

import ru.usu.gv.graph.Graph;
import ru.usu.gv.graph.Vertex;
import ru.usu.gv.gui.component.GVIntegerField;
import ru.usu.gv.utils.RandomUtilities;

import javax.swing.JPanel;

/**
 @author Sergey Pupyrev
  
Barabasi and Albert graph model.
*/

public class BAGenerator extends GraphGeneratorBase
{
	private GVIntegerField nodeCount;
	private GVIntegerField edgeCount;

	public String getTitle()
	{
		return "Barabasi, Albert";
	}

	public Graph generate(JPanel panel)
	{
		int n = nodeCount.getValue();
		int m = edgeCount.getValue();
		return generate(n, m);
	}

	@Override
	public void customizePanel(JPanel panel)
	{
		super.customizePanel(panel);

		nodeCount = new GVIntegerField("Node count", 30, true);
		edgeCount = new GVIntegerField("Edges per node", 5, true);

		panel.add(nodeCount);
		panel.add(edgeCount);
	}

	public static Graph generate(int n, int m)
	{
		Graph g = new Graph();

		for (int i = 0; i < n; i++)
		{
			g.addVertex(new Vertex());
		}

		for (int i = 0; i < n; i++)
		{
			if (i > 0)
			{
				for (int j = 0; j < m; j++)
				{
					int ind = randVertex(g);
					if (i != ind)
					{
						g.addEdge(g.getVertex(i), g.getVertex(ind));
						g.addEdge(g.getVertex(ind), g.getVertex(i));
					}
				}
			}
		}

		return g;
	}

	private static int randVertex(Graph graph)
	{
		int sum = 0;
		for (int i = 0; i < graph.getSize(); i++)
			sum += graph.getVertex(i).getEdgesSize();

		if (sum == 0)
		{
			return 0;
			//return RandomUtilities.nextInt(graph.getSize());
		}

		int rnd = RandomUtilities.nextInt(sum) + 1;
		int tec = 0, i = 0;
		while (true)
		{
			if (tec + graph.getVertex(i).getEdgesSize() >= rnd)
				break;
			tec += graph.getVertex(i).getEdgesSize();
			i++;
		}

		return i;
	}

}
